package map;

import gameStates.absGamesStates.AbsIngameState;
import logic.nodes.lod.blocks.Block;
import logic.nodes.lod.blocks.LeafBlock;

import com.jme.math.Vector3f;

public class BlocksCreator {
	
	private final float LEAF_SIZE = 256f;
	
	private Block rootBlock;
	private AbsIngameState ingameState;
	
	public BlocksCreator() {}
	
	public Block getRootBlock(int dimension, AbsIngameState ingameState) {
		this.ingameState = ingameState;
		
		float halfDimension = dimension / 2f;
		Vector3f rootLoc = new Vector3f(halfDimension, 0f, halfDimension);
		rootBlock = new Block(rootLoc, dimension, ingameState);
		
		Vector3f divDir = Vector3f.UNIT_X;
		createSubBlocks(rootBlock, divDir);
		
		return rootBlock;
	}
	
	private void createSubBlocks(Block parentBlock, Vector3f divDir) {
		float newX = parentBlock.getBox().xExtent;
		float newY = parentBlock.getBox().yExtent;
		float newZ = parentBlock.getBox().zExtent;
		Vector3f dir, nextDir;
		
		if(divDir == Vector3f.UNIT_X) {
			newX /= 2f;
			dir = divDir.mult(newX / 2f);
			nextDir = Vector3f.UNIT_Y;
		} else if(divDir == Vector3f.UNIT_Y) {
			newY /= 2f;
			dir = divDir.mult(newY / 2f);
			nextDir = Vector3f.UNIT_Z;
		} else {
			assert(divDir == Vector3f.UNIT_Z);
			newZ /= 2f;
			dir = divDir.mult(newZ / 2f);
			nextDir = Vector3f.UNIT_X;
			assert(newX == newY && newX == newZ);
		}
		
		Vector3f locA = parentBlock.getCenter().subtract(dir);
		Vector3f locB = parentBlock.getCenter().add(dir);
		
		if(newX <= LEAF_SIZE && newY <= LEAF_SIZE && newZ <= LEAF_SIZE) {
			assert(checkLeafBlocks(locA));
			LeafBlock leafA = new LeafBlock(locA, newX / 2f, ingameState);
			assert(checkLeafBlocks(locB));
			LeafBlock leafB = new LeafBlock(locB, newX / 2f, ingameState);
			parentBlock.addBlock(leafA);
			parentBlock.addBlock(leafB);
		} else {
			Block blockA = new Block(locA, newX, newY, newZ, ingameState);
			Block blockB = new Block(locB, newX, newY, newZ, ingameState);
			parentBlock.addBlock(blockA);
			parentBlock.addBlock(blockB);
			
			createSubBlocks(blockA, nextDir);
			createSubBlocks(blockB, nextDir);
		}
	}
	
	private boolean checkLeafBlocks(Vector3f loc) {
		for(LeafBlock a : LeafBlock.allLeafBlocks) {
			if(a.getCenter().equals(loc)) return false;
		}
		return true;
	}
}